﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;

namespace Sparrow.Reflection
{
    public class Metadata
    {
        public Metadata(Type type)
        {
            this.Type = type;

            this._Class = new Lazy<ClassMetadata>(this.InitClassMetadata, true);
            this._Constructors = new Lazy<MetadataCollection<ConstructorMetadata>>(this.InitConstructorMetadata, true);
            this._Properties = new Lazy<MetadataCollection<PropertyMetadata>>(this.InitPropertyMetadata, true);
            this._Fields = new Lazy<MetadataCollection<FieldMetadata>>(this.InitFieldMetadata, true);
            this._Methods = new Lazy<MetadataCollection<MethodMetadata>>(this.InitMethodMetadata, true);
        }

  
        #region Helper
        ClassMetadata InitClassMetadata()
        {
            return new ClassMetadata(this.Type);
        }

      
        MetadataCollection<ConstructorMetadata> InitConstructorMetadata()
        {
            MetadataCollection<ConstructorMetadata> list = new MetadataCollection<ConstructorMetadata>();
            int i = 1;
            foreach (var contructor in this.Type.GetConstructors())
            {
                list.Items.Add(contructor.Name + "#" + i.ToString(), new ConstructorMetadata(contructor));
                i++;
            }

            return list;
        }

        MetadataCollection<PropertyMetadata> InitPropertyMetadata()
        {
            MetadataCollection<PropertyMetadata> list = new MetadataCollection<PropertyMetadata>();

            foreach (var item in this.Type.GetProperties())
            {
                list.Items.Add(item.Name, new PropertyMetadata(item));

            }

            return list;
        }

        MetadataCollection<FieldMetadata> InitFieldMetadata()
        {
            MetadataCollection<FieldMetadata> list = new MetadataCollection<FieldMetadata>();

            foreach (var item in this.Type.GetFields())
            {
                list.Items.Add(item.Name, new FieldMetadata(item));

            }

            return list;
        }

        MetadataCollection<MethodMetadata> InitMethodMetadata()
        {
            MetadataCollection<MethodMetadata> list = new MetadataCollection<MethodMetadata>();

            foreach (var item in this.Type.GetMethods())
            {
                list.Items.Add(item.Name, new MethodMetadata(item));

            }

            return list;
        }

        #endregion

        Type Type
        {
            get;
            set;
        }

        Lazy<ClassMetadata> _Class;
        public ClassMetadata Class
        {
            get
            {
                return this._Class.Value;
            }
        }


        Lazy<MetadataCollection<ConstructorMetadata>> _Constructors;
        public MetadataCollection<ConstructorMetadata> Constructors
        {
            get
            {
                return this._Constructors.Value;
            }
        }


        Lazy<MetadataCollection<PropertyMetadata>> _Properties;
        public MetadataCollection<PropertyMetadata> Properties
        {
            get
            {
                return this._Properties.Value;
            }

        } 

        Lazy<MetadataCollection<FieldMetadata>> _Fields;
        public MetadataCollection<FieldMetadata> Fields
        {
            get
            {
                return this._Fields.Value;
            }

        } 

        Lazy<MetadataCollection<MethodMetadata>> _Methods;
        public MetadataCollection<MethodMetadata> Methods
        {
            get
            {
                return this._Methods.Value;
            }

        } 
  
    }
}
